package com.wei.czz.framework.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.wei.czz.common.constant.RedisConstant;
import com.wei.czz.common.enums.CommonEnum;
import com.wei.czz.common.enums.ResultEnum;
import com.wei.czz.common.exception.CzzException;
import com.wei.czz.common.po.UserPo;
import com.wei.czz.common.utils.SecurityUtils;
import com.wei.czz.framework.admin.dao.DeptUserDao;
import com.wei.czz.framework.admin.entity.DeptUserEntity;
import com.wei.czz.framework.admin.service.DeptUserService;
import lombok.AllArgsConstructor;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wei
 * date: 2022-08-19 15:52:59
 * className: DeptUserServiceImpl 部门与用户操作服务接口实现类
 * version: 1.0
 * description:
 */
@Service("deptUserService")
@AllArgsConstructor
public class DeptUserServiceImpl extends ServiceImpl<DeptUserDao, DeptUserEntity> implements DeptUserService {

    private static final Logger log = LoggerFactory.getLogger(DeptUserServiceImpl.class);

    private final RedissonClient redissonClient;

    @Override
    public void saveOrEdit(DeptUserEntity deptUser) {
        Long id = deptUser.getId();
        if (Objects.isNull(id)) {

            int count = baseMapper.insert(deptUser);
            log.info("保存部门与用户关联完成。count={}", count);
        } else {
            int count = baseMapper.updateById(deptUser);
            log.info("修改部门与用户关联完成。count={}", count);
        }
    }

    @Transactional
    @Override
    public void batchSave(List<DeptUserEntity> deptUserList) {
        boolean bool = this.saveBatch(deptUserList);
        log.info("批量插入部门与用户关联数据完成。size={} bool={}", deptUserList.size(), bool);
    }

    @Override
    public DeptUserEntity getDeptUser(Long userId, Long deptId) {
        LambdaQueryWrapper<DeptUserEntity> deptUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        deptUserLambdaQueryWrapper.eq(DeptUserEntity::getUserId, userId)
                .eq(DeptUserEntity::getDeptId, deptId)
                .eq(DeptUserEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 查询
        List<DeptUserEntity> deptUserList = baseMapper.selectList(deptUserLambdaQueryWrapper);
        log.info("查询部门关联用户完成。size={}", deptUserList.size());
        if (deptUserList.isEmpty()) {
            throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "部门关联用户不存在，请确认");
        }
        return deptUserList.get(0);
    }

    @Override
    public List<DeptUserEntity> findList(List<Long> deptIdList, List<Long> userIdList) {
        if (CollectionUtils.isEmpty(deptIdList) && CollectionUtils.isEmpty(userIdList)) {
            log.info("获取部门关联用户操作，传入的部门主键列表和用户主键列表均为空");
            return Collections.emptyList();
        }
        LambdaQueryWrapper<DeptUserEntity> deptUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        deptUserLambdaQueryWrapper.in(!CollectionUtils.isEmpty(deptIdList), DeptUserEntity::getDeptId, deptIdList)
                .in(!CollectionUtils.isEmpty(userIdList), DeptUserEntity::getUserId, userIdList)
                .eq(DeptUserEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 查询
        List<DeptUserEntity> deptUserList = baseMapper.selectList(deptUserLambdaQueryWrapper);
        log.info("批量查询部门关联用户完成。deptIdList={} userIdList={} size={}", deptIdList, userIdList,
                deptUserList.size());
        return deptUserList;
    }

    @Override
    public DeptUserEntity getDeptLeader(Long deptId) {

        // 获取部门关联用户列表
        List<DeptUserEntity> deptUserList = this.findList(Collections.singletonList(deptId), null);

        return deptUserList.stream()
                .filter(deptUser -> CommonEnum.ZERO.getValue().equals(deptUser.getLeaderStatus()))
                .findFirst()
                .orElse(null);
    }

    @Override
    public Long getDeptUserCount(List<Long> deptIdList) {
        if (CollectionUtils.isEmpty(deptIdList)) {
            log.info("获取部门关联用户数量，传入的部门主键列表为空");
            return CommonEnum.ZERO.getLongValue();
        }

        LambdaQueryWrapper<DeptUserEntity> deptUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        deptUserLambdaQueryWrapper.in(DeptUserEntity::getDeptId, deptIdList)
                .eq(DeptUserEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 查询
        Long count = baseMapper.selectCount(deptUserLambdaQueryWrapper);
        log.info("查询部门关联用户数量完成。count={}", count);
        return count;
    }

    @Transactional
    @Override
    public void batchUpdate(List<DeptUserEntity> deptUserList) {
        boolean bool = this.updateBatchById(deptUserList);
        log.info("批量修改部门关联用户完成。deptUserList.size={} bool={}", deptUserList.size(), bool);
    }

    @Override
    public void upDeptLeader(Long userId, Long deptId) {
        // 获取正在设置部门领导的用户
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        // 获取分布式锁对象
        RLock lock = redissonClient.getLock(RedisConstant.DEPT_USER + deptId);
        // 加锁
        lock.lock(30, TimeUnit.SECONDS);
        try {
            // 获取部门关联用户列表
            List<DeptUserEntity> deptUserList = this.findList(Collections.singletonList(deptId), null);

            DeptUserEntity _deptUser = deptUserList.stream()
                    .filter(deptUser -> CommonEnum.ONE.getValue().equals(deptUser.getLeaderStatus()))
                    .findFirst()
                    .orElse(null);
            if (Objects.nonNull(_deptUser)) {
                log.info("部门已存在部门主键。id={}", _deptUser.getDeptId());
                if (_deptUser.getUserId().equals(userId)) {
                    throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "该用户已是部门主管，不可重复设置");
                }
                throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "部门已有主管，不可重复设置");
            }

            _deptUser = deptUserList.stream()
                    .filter(deptUser -> deptUser.getUserId().equals(userId))
                    .findFirst()
                    .orElse(null);
            if (Objects.isNull(_deptUser)) {
                log.info("用户不属于该部门，无法设置");
                throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "用户不属于该部门，不可设置");
            }
            // 设置用户成为部门领导
            _deptUser.setLeaderStatus(CommonEnum.ZERO.getValue())
                    .setUpdateTime(date)
                    .setUpdateUser(userPo.getUsername())
                    .setUpdateUserId(userPo.getUserId());

            int count = baseMapper.updateById(_deptUser);
            log.info("设置部门领导完成。count={}", count);
        } finally {
            // 判断当前锁对象是否持有锁 并 持有该锁的线程与当前业务线程一致
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                // 解锁
                lock.unlock();
            }
        }
    }

    @Override
    public void deleteDeptLeader(Long userId, Long deptId) {
        // 获取正在取消部门领导的用户
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        // 获取分布式锁对象
        RLock lock = redissonClient.getLock(RedisConstant.DEPT_USER + deptId);
        // 加锁
        lock.lock(30, TimeUnit.SECONDS);
        try {
            // 获取部门关联用户列表
            List<DeptUserEntity> deptUserList = this.findList(Collections.singletonList(deptId), null);

            DeptUserEntity _deptUser = deptUserList.stream()
                    .filter(deptUser -> deptUser.getUserId().equals(userId))
                    .findFirst()
                    .orElse(null);
            if (Objects.isNull(_deptUser)) {
                log.info("用户不属于该部门，无法取消");
                throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "用户不属于该部门，不可取消");
            }
            if (CommonEnum.ONE.getValue().equals(_deptUser.getLeaderStatus())) {
                log.info("用户不是部门领导，无法取消。id={}", _deptUser.getId());
                throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "用户不是部门领导，不可取消");
            }

            // 设置用户成为部门领导
            _deptUser.setLeaderStatus(CommonEnum.ONE.getValue())
                    .setUpdateTime(date)
                    .setUpdateUser(userPo.getUsername())
                    .setUpdateUserId(userPo.getUserId());

            int count = baseMapper.updateById(_deptUser);
            log.info("用户取消部门领导完成。count={}", count);

        } finally {
            // 判断当前锁对象是否持有锁 并 持有该锁的线程与当前业务线程一致
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                // 解锁
                lock.unlock();
            }
        }
    }

    @Override
    public void deleteDeptUser(List<Long> deptIdList, List<Long> userIdList) {
        if (CollectionUtils.isEmpty(deptIdList) && CollectionUtils.isEmpty(userIdList)) {
            log.info("传入的部门主键列表和用户主键列表均为空");
            return;
        }
        // 获取操作用户
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        LambdaUpdateWrapper<DeptUserEntity> deptUserLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        deptUserLambdaUpdateWrapper.set(DeptUserEntity::getDeleteStatus, CommonEnum.ONE.getValue())
                .set(DeptUserEntity::getUpdateTime, date)
                .set(DeptUserEntity::getUpdateUserId, userPo.getUserId());
        deptUserLambdaUpdateWrapper.in(!CollectionUtils.isEmpty(deptIdList), DeptUserEntity::getDeptId, deptIdList)
                .in(!CollectionUtils.isEmpty(userIdList), DeptUserEntity::getUserId, userIdList)
                .eq(DeptUserEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 删除
        int count = baseMapper.update(deptUserLambdaUpdateWrapper);
        log.info("批量删除部门关联用户完成。count={}", count);
    }

}